package com.ddwl.order.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.ddwl.common.constant.*;
import com.ddwl.common.exception.CommonException;
import com.ddwl.common.exception.IllegalException;
import com.ddwl.common.exception.ParamException;
import com.ddwl.common.feign.api.*;
import com.ddwl.common.service.RedisService;
import com.ddwl.common.util.BeanConverUtils;
import com.ddwl.common.util.MySqlUtil;
import com.ddwl.common.util.UUIDGenerator;
import com.ddwl.order.dao.*;
import com.ddwl.order.dao.model.*;
import com.ddwl.order.service.dto.CreateOrderDto;
import com.ddwl.order.service.dto.OrderCouponDto;
import com.ddwl.order.service.dto.OrderSkuListDto;
import com.ddwl.order.util.ExcelUtil;
import com.ddwl.order.util.ExportOrderInfo;
import com.ddwl.schema.bo.base.PageBo;
import com.ddwl.schema.bo.gate.DingTalkBo;
import com.ddwl.schema.bo.gate.LoanSentSmsFlowBo;
import com.ddwl.schema.bo.gate.MobileRechargeRecordPageBo;
import com.ddwl.schema.bo.gate.SentSmsFlowDto;
import com.ddwl.schema.bo.gate.kuaiDi100.QueryBo;
import com.ddwl.schema.bo.gate.wechat.WxTemplateMsgBo;
import com.ddwl.schema.bo.goods.ItemListApiBo;
import com.ddwl.schema.bo.goods.SupplierBo;
import com.ddwl.schema.bo.message.TempSentSmsBo;
import com.ddwl.schema.bo.message.WebSocketMessageBo;
import com.ddwl.schema.bo.order.*;
import com.ddwl.schema.bo.shop.DistributionFeeBo;
import com.ddwl.schema.bo.wallet.DeductedSubsidyBo;
import com.ddwl.schema.util.DateUtil;
import com.ddwl.schema.vo.base.PageVo;
import com.ddwl.schema.vo.base.RestVo;
import com.ddwl.schema.vo.dist.DistVo;
import com.ddwl.schema.vo.gate.MobileRechargeRecordVo;
import com.ddwl.schema.vo.gate.RegionVo;
import com.ddwl.schema.vo.gate.kuaiDi100.QueryTrackVo;
import com.ddwl.schema.vo.goods.*;
import com.ddwl.schema.vo.order.*;
import com.ddwl.schema.vo.shop.DistributionFeeVo;
import com.ddwl.schema.vo.shop.ShopVo;
import com.ddwl.schema.vo.user.UserVo;
import com.ddwl.schema.vo.wallet.CouponVo;
import com.ddwl.schema.vo.wallet.UserCouponVo;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 类NewOrderServer.java的实现描述：订单处理
 *
 * @author zach
 * @Date :2020-06-02 12:57.
 */
@Service
@RefreshScope
@Slf4j
@RequiredArgsConstructor
public class OrderInfoServer {

    private final OrderInfoDao orderInfoDao;
    private final ThirdPartRecordDao thirdPartRecordDao;
    private final OrderSpuServer orderSpuServer;
    private final OrderAddressServer orderAddressServer;
    private final OrderPhaseServer orderPhaseServer;
    private final RabbitTemplate rabbitTemplate;
    private final RedisService redisService;
    private final GoodsApi goodsApi;
    private final GateApi gateApi;
    private final MessageApi messageApi;
    private final WalletApi walletApi;
    private final OrderInfoServer orderInfoServer;
    private final OrderAddrDao orderAddrDao;
    private final OrderInfoMasterDao orderInfoMasterDao;
    private final AfterSaleOrderDao afterSaleOrderDao;
    private final OrderSpuDao orderSpuDao;
    private final SeckillService seckillService;
    private final ShopApi shopApi;
    private final ShopAfterSaleOrderDao shopAfterSaleOrderDao;
    private final UserApi userApi;

    @Value("${ddwl.wxpay.seckill_expriation_time}")
    private Integer seckillExpriationTime;
    private final OrderPayServer orderPayServer;
    @Value("${ddwl.wxpay.expriation_time}")
    private Integer expirationTime;
    @Value("${ddwl.order.auto_receive_day}")
    private Integer autoReceiveDay;
    @Value("${ddwl.order.zt_auto_receive_day}")
    private Integer ztAutoReceiveDay;
    @Value("${ddwl.order.local_auto_receive_day}")
    private Integer local_AutoReceiveDay;
    //保修期限
    @Value("${ddwl.order.over_repair_time}")
    private Integer overRepairTime;

    /**
     * 下单
     *
     * @param createOrderBo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String createOrderNew(CreateOrderBo createOrderBo) {
        // 代理产品传入门店ID
        if (StringUtils.hasText(createOrderBo.getAgentShopId()) && (createOrderBo.getOperator().equals(createOrderBo.getSource()))) {
            CreateOrderBo.SkuList sku = createOrderBo.getSkuLists().get(0);
            ItemAgentVo itemAgent = goodsApi.agentInfo(sku.getItemId(), createOrderBo.getAgentShopId()).getResult();
            if (itemAgent != null) {
                if ((itemAgent.getBeginTime() == null || itemAgent.getBeginTime().isBefore(Instant.now()))
                        && (itemAgent.getExpireTime() == null || itemAgent.getExpireTime().isAfter(Instant.now()))
                        && BaseEnum.StatusEnum.ENABLE.getCode().equals(itemAgent.getStatus())) {
                    ShopVo shop = shopApi.getShopById(createOrderBo.getAgentShopId()).getResult();
                    if (Optional.ofNullable(shop.getDefaultTag()).orElse(1) != 1) {
                        createOrderBo.setSource(shop.getUserId());
                    }
                }
            }
        }
        //核验优惠券是否有效
        checkCoupon(createOrderBo.getUserCouponIds(), Boolean.FALSE);
        List<OrderCouponDto> couponDtos = getOrderCouponDtos(createOrderBo);
        //创建主订单
        OrderInfoMaster masterOrder = createMasterOrder(createOrderBo.getOperator(), createOrderBo.getSource());
        //询价并查询商品信息
        List<SkuBestPriceVo> skuBestPriceVo = getSkuBestPriceVos(createOrderBo);
        //校验创建订单信息
        verifyCreateInfo(createOrderBo, skuBestPriceVo, couponDtos);
        //组装并拆分订单信息
        List<CreateOrderDto> createOrderDtos = getCreateOrderDtos(createOrderBo, masterOrder, skuBestPriceVo, couponDtos);
        //计算配送费
        calculateFare(createOrderDtos, createOrderBo.getTotalFare());

        for (CreateOrderDto createOrderDto : createOrderDtos) {
            //创建订单
            createOrder(createOrderDto);
        }
        return masterOrder.getId();
    }

    private List<OrderCouponDto> getOrderCouponDtos(CreateOrderBo createOrderBo) {
        // 可用优惠券
        List<OrderCouponDto> couponDtos = new ArrayList<>();
        // FIXME 暂时每次下单只支持核销1张券
        if (!CollectionUtils.isEmpty(createOrderBo.getUserCouponIds())) {
            List<UserCouponVo> userCoupons = walletApi.userCoupons(createOrderBo.getUserCouponIds()).getResult();
            for (UserCouponVo userCoupon : userCoupons) {
                CouponVo couponVo = userCoupon.getCoupon();

                OrderCouponDto dto = new OrderCouponDto();
                dto.setUserCouponId(userCoupon.getId());
                dto.setType(couponVo.getType());
                dto.setCouponId(couponVo.getId());

                if (couponVo.getType().equals(WalletEnum.CouponType.REDUCTION.getCode())) {
                    dto.setMinAmount(couponVo.getMinAmount());
                    dto.setAmount(couponVo.getAmount());
                } else if (couponVo.getType().equals(WalletEnum.CouponType.VOUCHER.getCode())) {
                    dto.setAmount(couponVo.getAmount());
                } else {
                    dto.setItemId(couponVo.getItemId());
                }
                couponDtos.add(dto);
            }
        }
        return couponDtos;
    }

    private void checkCoupon(List<String> userCouponIds, Boolean use) {
        // FIXME
//        List<UserCouponVo> userCoupons = walletApi.userCoupons(userCouponIds).getResult();
        if (!CollectionUtils.isEmpty(userCouponIds)) {
            userCouponIds.forEach(userCouponId -> {
                RestVo restVo = walletApi.checkCoupon(userCouponId, use);
                if (!restVo.isSuccess()) {
                    throw new CommonException(restVo.getMsg());
                }
            });
        }
    }

    private void calculateFare(List<CreateOrderDto> createOrderDtos, BigDecimal totalFare) {
        if (null == totalFare || totalFare.compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }
        List<DistributionFeeBo> list = new ArrayList<>();
        createOrderDtos.forEach(coDto -> {
            if (!OrderEnum.DeliveryType.ZT.getCode().equals(coDto.getDeliveryType())) {
                DistributionFeeBo distributionFeeBo = list.stream()
                        .filter(dfBo -> coDto.getShopId().equals(dfBo.getShopId()))
                        .findFirst().orElse(null);
                if (null == distributionFeeBo) {
                    distributionFeeBo = new DistributionFeeBo();
                    distributionFeeBo.setShopId(coDto.getShopId());
                    distributionFeeBo.setType(coDto.getDeliveryType());
                    distributionFeeBo.setUserAddrId(coDto.getUserAdderId());
                    distributionFeeBo.setAmount(BigDecimal.ZERO);
                    list.add(distributionFeeBo);
                }

                BigDecimal price = coDto.getSkuLists().stream().map(
                                sku -> sku.getRealPrice().multiply(new BigDecimal(sku.getSkuQty()))
                                        .subtract(null == sku.getSubsidyPrice() ? BigDecimal.ZERO : sku.getSubsidyPrice()))
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                BigDecimal totalPrice = distributionFeeBo.getAmount().add(price);
                distributionFeeBo.setAmount(totalPrice);
                Integer quantity = (null == distributionFeeBo.getQuantity() ? 0 : distributionFeeBo.getQuantity()) + coDto.getQuantity();
                distributionFeeBo.setQuantity(quantity);
            }
        });
        Map<String, DistributionFeeVo> result = shopApi.fee(list).getResult();
        AtomicReference<BigDecimal> sumFare = new AtomicReference<>(BigDecimal.ZERO);
        result.forEach((shopId, vo) -> {
            List<CreateOrderDto> dtoList = createOrderDtos.stream().filter(coDto -> shopId.equals(coDto.getShopId())).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(dtoList)) {
                Integer type = vo.getType();
                ParamException.isTrue((BaseEnum.StatusEnum.DISABLE.getCode().equals(vo.getSendTag()) || null == vo.getFee()), "商家【" + dtoList.get(0).getShopName() + "】不支持当前配送方式");
                if (OrderEnum.DeliveryType.WS.getCode().equals(vo.getType())) {
                    if (null != vo.getDistance() && vo.getDistance() > vo.getBeyondDistance()) {
                        type = OrderEnum.DeliveryType.KD.getCode();
                    }
                }
                if (dtoList.size() == 1) {
                    dtoList.get(0).setFare(vo.getFee());
                    dtoList.get(0).setDeliveryType(type);
                } else {
                    BigDecimal fare = vo.getFee();
                    BigDecimal average = fare.divide(new BigDecimal(dtoList.size()), 2, RoundingMode.HALF_DOWN);
                    BigDecimal lastOne = fare.subtract(average.multiply(new BigDecimal(dtoList.size() - 1)));
                    for (int i = 0; i < dtoList.size(); i++) {
                        if (i == dtoList.size() - 1) {
                            dtoList.get(i).setFare(lastOne);
                        } else {
                            dtoList.get(i).setFare(average);
                        }
                        dtoList.get(0).setDeliveryType(type);
                    }
                }
            }
            sumFare.set(sumFare.get().add(null == vo.getFee() ? BigDecimal.ZERO : vo.getFee()));
        });
        ParamException.isTrue(sumFare.get().compareTo(totalFare) != 0, "配送费不正确");
    }

    /**
     * 内部调用不需要的校验
     *
     * @param createOrderBo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String createOrderApi(CreateOrderBo createOrderBo) {
        //创建主订单
        OrderInfoMaster masterOrder = createMasterOrder(createOrderBo.getOperator(), createOrderBo.getSource());
        //询价并查询商品信息
        List<SkuBestPriceVo> skuBestPriceVo = getSkuBestPriceVos(createOrderBo);
        //组装并拆分订单信息
        List<CreateOrderDto> createOrderDtos = getCreateOrderDtos(createOrderBo, masterOrder, skuBestPriceVo, null);
        for (CreateOrderDto createOrderDto : createOrderDtos) {
            //创建订单
            createOrder(createOrderDto);
        }
        return masterOrder.getId();
    }

    private void verifyCreateInfo(CreateOrderBo createOrderBo, List<SkuBestPriceVo> skuBestPriceVo, List<OrderCouponDto> couponDtos) {
        createOrderBo.getSkuLists().forEach(skuList -> {
            if (skuList.getDeliveryType() == null || OrderEnum.DeliveryType.KD.getCode().equals(skuList.getDeliveryType())) {
                ParamException.isTrue(StrUtil.isBlank(skuList.getUserAdderId()) && StrUtil.isBlank(createOrderBo.getUserAdderId()), "快递订单收货地址不能为空");
            }
            if (OrderEnum.DeliveryType.ZT.getCode().equals(skuList.getDeliveryType())) {
                ParamException.isTrue(StrUtil.isBlank(skuList.getUserMobile()), "自提订单收件人联系电话不能为空");
            }
        });
        ParamException.isTrue(skuBestPriceVo.size() != createOrderBo.getSkuLists().size(), "商品信息有变更请重新下单");
        ParamException.isTrue(skuBestPriceVo.stream().map(SkuBestPriceVo::getItemStatus).reduce(0, Integer::sum) < skuBestPriceVo.size(), "存在被下架商品请重新下单");
        //BigDecimal orderReadAmount = skuBestPriceVo.stream().map(o -> o.getRealPrice().multiply(new BigDecimal(o.getSkuQty()))).reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal orderReadAmount = BigDecimal.ZERO;
        //订单可用津贴金额
        BigDecimal orderSubsidyPrice = BigDecimal.ZERO;
        for (SkuBestPriceVo vo : skuBestPriceVo) {
            List<OrderCouponDto> collect = couponDtos.stream().filter(dto -> vo.getItemId().equals(dto.getItemId())).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(collect)) {
                int qty = (vo.getSkuQty() - collect.size()) > 0 ? (vo.getSkuQty() - collect.size()) : 0;
                orderReadAmount = orderReadAmount.add(vo.getRealPrice().multiply(new BigDecimal(qty)));
                orderSubsidyPrice = orderSubsidyPrice.add(vo.getSubsidyPrice().multiply(new BigDecimal(qty)));
            } else {
                orderReadAmount = orderReadAmount.add(vo.getRealPrice().multiply(new BigDecimal(vo.getSkuQty())));
                orderSubsidyPrice = orderSubsidyPrice.add(vo.getSubsidyPrice().multiply(new BigDecimal(vo.getSkuQty())));
            }
        }

        if (createOrderBo.getSubsidyPrice() != null) {
            //获取用户的津贴余额
            BigDecimal userSubsidy = walletApi.getSubsidy(createOrderBo.getOperator(), createOrderBo.getProduct()).getResult().getAmount();
            ParamException.isTrue(userSubsidy.compareTo(createOrderBo.getSubsidyPrice()) < 0, "用户津贴余额不足");
            //订单可用津贴金额
            //BigDecimal orderSubsidyPrice = skuBestPriceVo.stream().map(SkuBestPriceVo::getSubsidyPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
            ParamException.isTrue(createOrderBo.getSubsidyPrice().compareTo(orderSubsidyPrice) > 0, "津贴抵扣金额超过了当前订单可抵扣金额");
            //订单实际需要支付金额
            orderReadAmount = orderReadAmount.subtract(orderSubsidyPrice);
        }
        //如果传了订单金额则进行订单金额校验
        if (createOrderBo.getPrice() != null) {
            ParamException.isTrue(orderReadAmount.compareTo(createOrderBo.getPrice()) != 0, "订单价格不正确");
        }
        //校验下单数量
        for (SkuBestPriceVo vo : skuBestPriceVo) {
            if (vo.getLimitTimeFlag() != null && vo.getLimitTimeFlag() == 1) {
                ParamException.isTrue(vo.getSkuQty() + vo.getSalesCount() > vo.getLimitCount(), "限时购商品数量不足,请移出后下单");
            }
        }
        //校验下单数量
        for (SkuBestPriceVo vo : skuBestPriceVo) {
            if (vo.getLimitFlag() != null && vo.getLimitFlag() == 1) {
                checkLimitSkuCount(vo, createOrderBo.getOperator());
            }
        }
    }

    /**
     * 校验限购数量
     */
    private void checkLimitSkuCount(SkuBestPriceVo vo, String userId) {
        ParamException.isTrue(vo.getSkuQty() > vo.getLimitQuantity(), "超过限购数量,该商品只能够买" + vo.getLimitQuantity() + "件");
        QueryOrderListBo bo = new QueryOrderListBo();
        //userAp
        bo.setItemId(vo.getItemId());
        bo.setUserIds(Arrays.asList(userId));
        String[] array = {"0", "1", "2", "3", "5"};
        List<String> list = Arrays.asList(array);
        bo.setStatuss(list);
        Integer[] array2 = {0, 1, 5};
        List<Integer> list2 = Arrays.asList(array2);
        bo.setIsAfterSales(list2);
        List<OrderSpu> spus = orderSpuDao.getSpuOrderList(bo);
        if (!CollectionUtils.isEmpty(spus) && vo.getLimitQuantity() != null && vo.getLimitQuantity() != 0) {
            int qty = spus.stream().mapToInt(OrderSpu::getSkuQty).sum();
            ParamException.isTrue(vo.getSkuQty() + qty > vo.getLimitQuantity(), "超过限购数量,该商品只能够买" + vo.getLimitQuantity() + "件");
        }
    }

    /**
     * 根据订单的请求信息进行商品询价
     *
     * @param createOrderBo
     * @return
     */
    public List<SkuBestPriceVo> getSkuBestPriceVos(CreateOrderBo createOrderBo) {
        QuerySkuPriceBo querySkuPriceBo = new QuerySkuPriceBo();
        List<QuerySkuPriceBo.Sku> skus = new ArrayList<>();
        createOrderBo.getSkuLists().stream().forEach(skuList -> {
            QuerySkuPriceBo.Sku sku = new QuerySkuPriceBo.Sku();
            sku.setQty(skuList.getSkuQty());
            sku.setSkuId(skuList.getSkuId());
            //秒杀订单
            if (1 == createOrderBo.getOrderType()) {
                sku.setKillOrderId(skuList.getActivityId());
            }
            //砍价订单
            if (2 == createOrderBo.getOrderType()) {
                sku.setBargainOrderId(skuList.getActivityId());
            }
            skus.add(sku);
        });
        querySkuPriceBo.setSkus(skus);
        querySkuPriceBo.setUserId(createOrderBo.getOperator());
        querySkuPriceBo.setSubsidyAmount(createOrderBo.getSubsidyPrice());

        return goodsApi.querySkuPrice(querySkuPriceBo).getResult();
    }

    /**
     * 组装并拆分订单信息
     *
     * @param createOrderBo
     * @param masterOrder
     * @param skuBestPriceVo
     * @param couponDtos     使用的优惠券
     * @return
     */
    private List<CreateOrderDto> getCreateOrderDtos(CreateOrderBo createOrderBo, OrderInfoMaster masterOrder, List<SkuBestPriceVo> skuBestPriceVo,
                                                    List<OrderCouponDto> couponDtos) {
        List<OrderSkuListDto> orderSkuListDto = BeanConverUtils.convertBeanList(skuBestPriceVo, OrderSkuListDto.class);
        //组装商品收货地址和配送信息
        orderSkuListDto.forEach(o -> {
            createOrderBo.getSkuLists().forEach(sku -> {
                if (sku.getSkuId().equals(o.getSkuId())) {
                    if (sku.getDeliveryType() != null) {
                        o.setDeliveryType(sku.getDeliveryType());
                    } else {
                        o.setDeliveryType(OrderEnum.DeliveryType.KD.getCode());
                    }
                    if (StrUtil.isNotBlank(sku.getUserAdderId())) {
                        o.setUserAdderId(sku.getUserAdderId());
                    } else {
                        o.setUserAdderId(createOrderBo.getUserAdderId());
                    }
                    if (StrUtil.isNotEmpty(sku.getRemark())) {
                        o.setRemark(sku.getRemark());
                    }
                    if (StrUtil.isNotBlank(sku.getUserMobile())) {
                        o.setMobile(sku.getUserMobile());
                    }
                    if (null == o.getAgentFlag()) {
                        o.setAgentFlag(BaseEnum.StatusEnum.DISABLE.getCode());
                    }
                    if (null == o.getCharityFlag()) {
                        o.setCharityFlag(BaseEnum.StatusEnum.DISABLE.getCode());
                    }
                    if (null == o.getDiscountFlag()) {
                        o.setDiscountFlag(BaseEnum.StatusEnum.DISABLE.getCode());
                    }
                    if (null == o.getLimitTimeFlag()) {
                        o.setLimitTimeFlag(BaseEnum.StatusEnum.DISABLE.getCode());
                    }
                }
            });
        });
        List<CreateOrderDto> createOrderDtos = new ArrayList<>();
        orderSkuListDto.forEach(o -> {
            CreateOrderDto createOrderDto = createOrderDtos.stream().filter(dto ->
                    o.getShopId().equals(dto.getShopId()) &&
                            StrUtil.equals(o.getSupplierId(), dto.getSupplierId()) &&
                            o.getDeliveryType().equals(dto.getDeliveryType()) &&
                            StrUtil.equals(o.getUserAdderId(), dto.getUserAdderId()) &&
                            o.getLimitTimeFlag().equals(dto.getLimitTimeFlag()) &&
                            o.getDiscountFlag().equals(dto.getDiscountFlag()) &&
                            o.getCharityFlag().equals(dto.getCharityFlag()) &&
                            o.getAgentFlag().equals(dto.getAgentFlag())
            ).findFirst().orElse(null);
            if (createOrderDto == null) {
                createOrderDto = createOrderDto(createOrderBo, masterOrder.getId(), o);
                createOrderDtos.add(createOrderDto);
            }
            Integer quantity = Optional.ofNullable(createOrderDto.getQuantity()).orElse(0) + Optional.ofNullable(o.getSkuQty()).orElse(0);
            createOrderDto.setQuantity(quantity);
            createOrderDto.getSkuLists().add(o);
            //过滤出商品兑换券
            if (null != couponDtos) {
                OrderCouponDto orderCouponDto = couponDtos.stream().filter(coupon -> o.getItemId().equals(coupon.getItemId())).findFirst().orElse(null);
                if (null != orderCouponDto) {
                    createOrderDto.getCouponList().add(orderCouponDto);
                    couponDtos.remove(orderCouponDto);
                }
            }
        });
        return createOrderDtos;
    }

    private CreateOrderDto createOrderDto(CreateOrderBo createOrderBo, String masterOrderId, OrderSkuListDto o) {
        CreateOrderDto createOrderDto;
        createOrderDto = new CreateOrderDto();
        if (o.getDeliveryType() == null) {
            createOrderDto.setDeliveryType(OrderEnum.DeliveryType.KD.getCode());
        } else {
            createOrderDto.setDeliveryType(o.getDeliveryType());
        }
        createOrderDto.setMasterOrderId(masterOrderId);
        createOrderDto.setIsShoppingCart(createOrderBo.getIsShoppingCart());
        createOrderDto.setNote(createOrderBo.getNote());
        createOrderDto.setOrderType(createOrderBo.getOrderType());
        if (o.getLimitTimeFlag() != null && BaseEnum.StatusEnum.ENABLE.getCode().equals(o.getLimitTimeFlag())) {
            createOrderDto.setOrderType(OrderEnum.OrderWay.LIMIT_TIME.getCode());
            createOrderDto.setLimitTimeFlag(o.getLimitTimeFlag());
        } else {
            createOrderDto.setLimitTimeFlag(BaseEnum.StatusEnum.DISABLE.getCode());
        }
        if (BaseEnum.StatusEnum.ENABLE.getCode().equals(o.getDiscountFlag())) {
            createOrderDto.setOrderType(OrderEnum.OrderWay.DISCOUNT.getCode());
            createOrderDto.setDiscountFlag(o.getDiscountFlag());
        } else {
            createOrderDto.setDiscountFlag(BaseEnum.StatusEnum.DISABLE.getCode());
        }
        createOrderDto.setShopId(o.getShopId());
        createOrderDto.setShopName(o.getShopName());
        createOrderDto.setSource(createOrderBo.getSource());
        createOrderDto.setSupplierId(o.getSupplierId());
        createOrderDto.setProduct(createOrderBo.getProduct());
        if (o.getUserAdderId() != null) {
            createOrderDto.setUserAdderId(o.getUserAdderId());
        } else {
            createOrderDto.setUserAdderId(createOrderBo.getUserAdderId());
        }
        createOrderDto.setCharityFlag(o.getCharityFlag());
        createOrderDto.setAgentFlag(o.getAgentFlag());
        createOrderDto.setAgentShopId(createOrderBo.getAgentShopId());
        createOrderDto.setUserId(createOrderBo.getOperator());
        createOrderDto.setUserName(createOrderBo.getOperatorName());
        createOrderDto.setSkuLists(new ArrayList<>());
        createOrderDto.setCouponList(new ArrayList<>());
        if (StrUtil.isNotBlank(o.getRemark())) {
            createOrderDto.setNote(o.getRemark());
        }
        return createOrderDto;
    }

    /**
     * 创建订单
     *
     * @param createOrderDto
     * @return
     */
    public OrderInfo createOrder(CreateOrderDto createOrderDto) {
        //初始化订单信息
        OrderInfo orderInfo = createOrderInfo(createOrderDto);
        //保存订单商品信息
        List<OrderSpu> orderSpus = orderSpuServer.createOrderSpu(orderInfo, createOrderDto);
        orderInfo.setSkuSnapshoot(JSON.toJSONString(orderSpus));
        //生成订单支付信息
        createOrderPay(orderInfo);
        //创建订单收货信息
        String orderAddrRegionId = orderAddressServer.createOrderAddr(createOrderDto, orderInfo);
        orderInfo.setRegionId(orderAddrRegionId);
        orderInfoDao.insert(orderInfo);
        //订单处理完成的后置消息
        createOrderAfter(createOrderDto, orderInfo, orderSpus);
        return orderInfo;
    }

    //生成订单支付信息
    private void createOrderPay(OrderInfo orderInfo) {
        //只有订单金额大于0且状态是未支付的订单才去生成支付信息
        if (orderInfo.getRealAmount().compareTo(BigDecimal.ZERO) > 0 && OrderEnum.OrderStatus.UN_PAY.getCode().equals(orderInfo.getStatus())) {
            orderPayServer.createOrderPay(orderInfo);
        }
    }

    /**
     * 订单创建完成后
     * 1.发送订单关闭延迟任务
     * 2.扣除库存
     * 3.扣除津贴
     * 4.移除购物车
     *
     * @param createOrderDto
     * @param orderInfo
     * @param orderSpus
     */
    private void createOrderAfter(CreateOrderDto createOrderDto, OrderInfo orderInfo, List<OrderSpu> orderSpus) {
        sentOrderTimeoutMsg(orderInfo);
        //扣除库存
        changeOrderSkuInventory(orderInfo, BaseEnum.StatusEnum.ENABLE.getCode());
        //如果有使用津贴扣除津贴
        if (orderInfo.getSubsidyPrice() != null && orderInfo.getSubsidyPrice().compareTo(BigDecimal.ZERO) > 0) {
            DeductedSubsidyBo bo = new DeductedSubsidyBo();
            bo.setAmount(orderInfo.getSubsidyPrice());
            bo.setOrderId(orderInfo.getId());
            bo.setUserId(createOrderDto.getUserId());
            bo.setProduct(orderInfo.getProduct());
            walletApi.deductedSubsidy(bo);
        }
        //新增统计数据
        redisService.getHashOps().increment(RedisKey.DATA_TODAY_CHART.getKey(), DataEnum.TodayData.ORDERS.name(), 1);
        //如果是购物车下单移除购物车
        if (BaseEnum.StatusEnum.ENABLE.getCode().equals(createOrderDto.getIsShoppingCart())) {
            ((OrderInfoServer) AopContext.currentProxy()).deleteShoppingCart(orderSpus, orderInfo.getUserId());
        }
    }


    public String createBargainOrder(BargainActivityOrderBo bo) {
        CreateOrderBo createOrderBo = BeanConverUtils.convertBean(bo, CreateOrderBo.class);
        createOrderBo.setSkuLists(BeanConverUtils.convertBeanList(bo.getSkuLists(), CreateOrderBo.SkuList.class));
        createOrderBo.setOrderType(2);
        createOrderBo.setOperator(bo.getUserId());
        createOrderBo.setOperatorName(bo.getUserName());
        return createOrderApi(createOrderBo);
    }

    /**
     * 创建订单
     *
     * @param createOrderDto
     * @return
     */
    private OrderInfo createOrderInfo(CreateOrderDto createOrderDto) {
        List<OrderSkuListDto> skuLists = createOrderDto.getSkuLists();
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setId(UUIDGenerator.getTimeUUID());
        orderInfo.setSupplierId(createOrderDto.getSupplierId());
        orderInfo.setShopId(createOrderDto.getShopId());
        orderInfo.setDeliveryType(createOrderDto.getDeliveryType());
        orderInfo.setUserId(createOrderDto.getUserId());
        orderInfo.setUserName(createOrderDto.getUserName());
        orderInfo.setMasterOrderId(createOrderDto.getMasterOrderId());
        orderInfo.setProduct(createOrderDto.getProduct());
        orderInfo.setNote(createOrderDto.getNote());
        orderInfo.setOrderType(createOrderDto.getOrderType());
        orderInfo.setAfterSaleCount(0);
        orderInfo.setIsAfterSale(0);
        orderInfo.setMobile(skuLists.get(0).getMobile());
        orderInfo.setCharityFlag(createOrderDto.getCharityFlag());
        orderInfo.setAgentFlag(createOrderDto.getAgentFlag());
        orderInfo.setAgentShopId(createOrderDto.getAgentShopId());
        //默认微信支付
        orderInfo.setPaymentType(0);
        //订单默认为一次性结清
        orderInfo.setPayType(OrderEnum.PayType.ONE.getCode());
        orderInfo.setItemCount(skuLists.size());
        orderInfo.setSource(createOrderDto.getSource());
        orderInfo.setSettlementStatus(OrderEnum.SettlementStatus.CRE.getCode());
        orderInfo.setPayAmount(BigDecimal.ZERO);

        //津贴
        BigDecimal subsidy = BigDecimal.ZERO;
        //订单要付多少钱
        BigDecimal amount = BigDecimal.ZERO;
        //实际要支付多少钱
        BigDecimal realAmount = BigDecimal.ZERO;
        StringJoiner couponId = new StringJoiner(",");

        for (OrderSkuListDto sku : skuLists) {
            BigDecimal averageSubsidy = (null == sku.getSubsidyPrice() ? BigDecimal.ZERO : sku.getSubsidyPrice()).divide(new BigDecimal(sku.getSkuQty()), 2, RoundingMode.HALF_DOWN);
            amount = amount.add(sku.getPrice().multiply(new BigDecimal(sku.getSkuQty())));
            List<OrderCouponDto> orderCouponDtoList = new ArrayList<>();
            if (!CollectionUtils.isEmpty(createOrderDto.getCouponList())) {
                orderCouponDtoList = createOrderDto.getCouponList().stream().filter(coupon -> sku.getItemId().equals(coupon.getItemId())).collect(Collectors.toList());
            }
            if (!CollectionUtils.isEmpty(orderCouponDtoList)) {
                int qty = (sku.getSkuQty() > orderCouponDtoList.size()) ? sku.getSkuQty() - orderCouponDtoList.size() : 0;
                realAmount = realAmount.add(
                        sku.getRealPrice().multiply(new BigDecimal(qty))
                                .subtract(averageSubsidy.multiply(new BigDecimal(qty)))
                );
                subsidy = subsidy.add(averageSubsidy.multiply(new BigDecimal(qty)));
                orderCouponDtoList.forEach(dto -> {
                    couponId.add(dto.getUserCouponId());
                    createOrderDto.getCouponList().remove(dto);
                });
            } else {
                subsidy = subsidy.add(null == sku.getSubsidyPrice() ? BigDecimal.ZERO : sku.getSubsidyPrice());
                realAmount = realAmount.add(
                        sku.getRealPrice().multiply(new BigDecimal(sku.getSkuQty()))
                                .subtract(sku.getSubsidyPrice())
                );
            }
        }

        orderInfo.setSubsidyPrice(subsidy);
        //orderInfo.setSubsidyPrice(createOrderDto.getSkuLists().stream().map(oslDto -> null == oslDto.getSubsidyPrice() ? BigDecimal.ZERO : oslDto.getSubsidyPrice()).reduce(BigDecimal.ZERO, BigDecimal::add));
        //默认平台订单
        orderInfo.setPlatformTag(0);
        orderInfo.setFare(createOrderDto.getFare());
        //计算出订单要付多少钱
        orderInfo.setAmount(amount);
//        orderInfo.setAmount(skuLists.stream().map(skulists ->
//                skulists.getPrice().multiply(new BigDecimal(skulists.getSkuQty()))
//        ).reduce(BigDecimal.ZERO, BigDecimal::add));

        //计算出订单实际要支付多少钱
        orderInfo.setRealAmount(realAmount);
//        orderInfo.setRealAmount(skuLists.stream().map(skulists ->
//                skulists.getRealPrice().multiply(new BigDecimal(skulists.getSkuQty())).subtract(skulists.getSubsidyPrice())
//        ).reduce(BigDecimal.ZERO, BigDecimal::add));

        orderInfo.setCouponId(couponId.toString());

        if (null != orderInfo.getFare()) {
            orderInfo.setAmount(orderInfo.getAmount().add(orderInfo.getFare()));
            orderInfo.setRealAmount(orderInfo.getRealAmount().add(orderInfo.getFare()));
        }
        //如果是零元单不需要支付
        if (orderInfo.getRealAmount().compareTo(BigDecimal.ZERO) <= 0) {
            orderInfo.setStatus(OrderEnum.OrderStatus.PAYED.getCode());
            orderInfo.setPayAmount(BigDecimal.ZERO);
            orderInfo.setPayTime(Instant.now());
        } else {
            orderInfo.setStatus(OrderEnum.OrderStatus.UN_PAY.getCode());
        }
        orderInfo.setExpirationTime(DateUtil.addMinutes(Instant.now(), expirationTime));
        //秒杀订单单独设置
        if (orderInfo.getOrderType().equals(1)) {
            orderInfo.setExpirationTime(DateUtil.addMinutes(Instant.now(), seckillExpriationTime));
        }
        ShopVo shopVoRestVo = shopApi.getShopForApi(orderInfo.getShopId()).getResult();
        if (shopVoRestVo != null) {
            orderInfo.setShopName(shopVoRestVo.getName());
            //如果默认店铺
            if (shopVoRestVo.getDefaultTag() != 1) {
                orderInfo.setPlatformTag(1);
            } else {
                orderInfo.setPlatformTag(0);
            }
        }
        if (orderInfo.getRealAmount().compareTo(BigDecimal.ZERO) <= 0) {
            if (StringUtils.hasText(orderInfo.getCouponId())) {
                checkCoupon(Arrays.asList(orderInfo.getCouponId()), Boolean.TRUE);
            }
        }
        return orderInfo;
    }

    /**
     * 创建主订单
     *
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public synchronized OrderInfoMaster createMasterOrder(String userId, String source) {
        OrderInfoMaster orderInfoMaster = new OrderInfoMaster();
        orderInfoMaster.setId(UUIDGenerator.getTimeUUID());
        orderInfoMaster.setUserId(userId);
        orderInfoMaster.setStatus(OrderEnum.OrderStatus.UN_PAY.getCode());
        orderInfoMaster.setSource(source);
        //保存订单
        orderInfoMasterDao.insert(orderInfoMaster);
        return orderInfoMaster;
    }

    /**
     * 分页查询订单包含商品信息
     *
     * @param pageBo
     * @return
     */
    public PageVo<OrderInfoListVo> getPage(PageBo<QueryOrderListBo> pageBo) {
        PageVo<OrderInfoListVo> pageVo = new PageVo<>();
        pageVo.setPage(pageBo.getPage());
        pageVo.setSize(pageBo.getPageSize());
        PageHelper.startPage(pageBo.getPage(), pageBo.getPageSize(), MySqlUtil.orderBy(pageBo.getSort(), pageBo.isAsc()));
        Page<OrderInfo> pageable = (Page<OrderInfo>) orderInfoDao.queryOrderSpuList(pageBo.getParam());
        pageVo.setTotal(pageable.getTotal());
        List<OrderInfo> orders = pageable.getResult();
        if (orders.isEmpty()) {
            pageVo.setData(new ArrayList<>());
            return pageVo;
        }
        Set<String> agentShopIds = new HashSet<>();
        Set<String> userIds = new HashSet<>();
        orders.forEach(order -> {
            if (StringUtils.hasText(order.getAgentShopId())) {
                agentShopIds.add(order.getAgentShopId());
            }
            userIds.add(order.getUserId());
        });
        Map<String, String> shopNameMap;
        if (!agentShopIds.isEmpty()) {
            List<ShopVo> shops = shopApi.getShopListByIds(agentShopIds).getResult();
            shopNameMap = shops.stream().collect(Collectors.toMap(ShopVo::getId, ShopVo::getName));
        } else {
            shopNameMap = new HashMap<>(0);
        }
        List<UserVo> users = userApi.getUserByIds(userIds).getResult();
        Map<String, UserVo> userMap = users.stream().collect(Collectors.toMap(UserVo::getId, Function.identity()));
        pageVo.setData(orders.stream().map(order -> {
            OrderInfoListVo vo = BeanConverUtils.convertBean(order, OrderInfoListVo.class);
            if (!CollectionUtils.isEmpty(order.getSpus())) {
                vo.setSpus(BeanConverUtils.convertBeanList(order.getSpus(), OrderSpuVo.class));
            }
            if (StringUtils.hasText(order.getAgentShopId()) && !order.getAgentShopId().equals(order.getShopId())) {
                vo.setShopName(String.format("%s-%s", shopNameMap.get(order.getAgentShopId()), vo.getShopName()));
            }
            vo.setUser(userMap.get(order.getUserId()));
            return vo;
        }).collect(Collectors.toList()));
        return pageVo;
    }

    public PageVo<OrderInfoListVo> getWbmShopPage(PageBo<QueryOrderListBo> pageBo) {
        return getPage(pageBo);
    }


    /**
     * 查询主订单列表"
     *
     * @param boPageBo
     * @return
     */
    public PageVo<OrderInfoListApiVo> getMainApiPage(PageBo<OrderListApiBo> boPageBo) {
        PageHelper.startPage(boPageBo.getPage(), boPageBo.getPageSize(), MySqlUtil.orderBy(boPageBo.getSort(), boPageBo.isAsc()));
        OrderListApiBo bo = boPageBo.getParam();
        ParamException.isTrue(bo.getAppId() == null, "appID为空");
        ParamException.isTrue(bo.getTimestamp() == null, "请求时间为空");
        SupplierBo supplierBo = new SupplierBo();
        supplierBo.setAppId(bo.getAppId());
        RestVo<PageVo<SupplierVo>> pageVoRestVo = goodsApi.querySupplierCategory(supplierBo);
        List<SupplierVo> data = pageVoRestVo.getResult().getData();
        ParamException.isTrue(data == null || data.size() == 0, "appID不存在");
        List<String> supplierList = data.stream().map(supplierVo -> supplierVo.getId()).collect(Collectors.toList());
        bo.setSupplierList(supplierList);
        //ParamException.isFalse(ThirdPartEnum.ThirdPartCode.isIncludeCode(bo.getAppId()),"appID不存在或者已过期");
        PageInfo<OrderInfo> info = new PageInfo(orderInfoDao.queryOrderSpuApiList(boPageBo.getParam()));
        List<OrderInfoListApiVo> list = BeanConverUtils.convertBeanList(info.getList(), OrderInfoListApiVo.class);
        return new PageVo<>(info.getTotal(), boPageBo.getPage(), boPageBo.getPageSize(), list);
    }

    /**
     * 查询主订单列表"
     *
     * @param id
     * @param userId
     * @return
     */
    public OrderInfoMasterVo getMasterOrder(String id, String userId) {
        ParamException.isBlank(id, "订单id不存在");
        OrderInfoMaster orderInfoMaster = new OrderInfoMaster();
        orderInfoMaster.setId(id);
        orderInfoMaster.setUserId(userId);
        OrderInfoMasterVo orderInfoMasterVo = BeanConverUtils.convertBean(orderInfoMasterDao.selectOne(orderInfoMaster), OrderInfoMasterVo.class);

        return orderInfoMasterVo;
    }

    /**
     * 查询用户订单详细信息
     *
     * @param orderId
     * @param userId
     * @return
     */
    public OrderDetailVo getDetail(String orderId, String userId) {
        OrderDetailVo orderDetailVo = new OrderDetailVo();
        OrderInfoVo orderInfoVo = BeanConverUtils.convertBean(orderInfoDao.selectByPrimaryKey(orderId), OrderInfoVo.class);
        ParamException.isNull(orderDetailVo);
//        if(StringUtils.hasText(userId)||StringUtils.hasText(fenxiaoId)){
//            IllegalException.isFalse(orderInfoVo.getUserId().equals(userId)||orderInfoVo.getUserId().equals(fenxiaoId));
//        }
        orderDetailVo.setOrderInfoVo(orderInfoVo);
        orderDetailVo.setOrderAddrVo(orderAddressServer.getOrderAddr(orderId));
        orderDetailVo.setSpuVos(orderSpuServer.getOrderSpu(orderId));
        //售后信息
        QueryAfterSaleOrderListBo bo = new QueryAfterSaleOrderListBo();
        bo.setOrderId(orderId);
        List<AfterSaleOrder> afterSaleOrders = afterSaleOrderDao.queryAfterSaleOrderList(bo);
        orderDetailVo.setAfterSaleOrderVos(BeanConverUtils.convertBeanList(afterSaleOrders, AfterSaleOrderVo.class));
        orderDetailVo.setPhaseVos(orderPhaseServer.getOrderPhase(orderId));
        orderDetailVo.setShopVo(shopApi.getShopForApi(orderInfoVo.getShopId()).getResult());
        return orderDetailVo;
    }

    public OrderDetailVo getShopOrderDetail(String userId, String orderId) {
        OrderDetailVo orderDetailVo = getOrderDetail(orderId);
        //ShopVo shopVo = shopApi.judgeUserHasShop(userId, orderDetailVo.getOrderInfoVo().getShopId()).getResult();
        //IllegalException.isNull(shopVo,"您无权访问该数据");
        //商家过滤取件码
        if (orderDetailVo.getOrderAddrVo() != null) {
            orderDetailVo.getOrderAddrVo().setDeliveryCode(null);
        }
        if (!CollectionUtils.isEmpty(orderDetailVo.getOrderAddrVos())) {
            orderDetailVo.getOrderAddrVos().forEach(orderAddrVo -> {
                orderAddrVo.setDeliveryCode(null);
            });
        }
        return orderDetailVo;
    }

    public void shopUpdateOrderRemark(OrderRemarkUpdaeBo updaeBo) {
        OrderInfo orderInfo = orderInfoDao.selectByPrimaryKey(updaeBo.getOrderId());
        ParamException.isNull(orderInfo, "订单不存在");
        IllegalException.isFalse(orderInfo.getShopId().equals(updaeBo.getShopId()), "您无权访问该数据");
        OrderInfo update = new OrderInfo();
        update.setId(updaeBo.getOrderId());
        update.setRemark(updaeBo.getRemark());
        orderInfoDao.updateByPrimaryKeySelective(update);
    }


    /**
     * 查询订单详细信息
     *
     * @param orderId
     * @return
     */
    public OrderDetailVo getOrderDetail(String orderId) {
        OrderDetailVo orderDetailVo = new OrderDetailVo();
        OrderInfoVo orderInfoVo = BeanConverUtils.convertBean(orderInfoDao.selectByPrimaryKey(orderId), OrderInfoVo.class);
        ParamException.isNull(orderInfoVo);
        orderDetailVo.setOrderInfoVo(orderInfoVo);
        orderDetailVo.setOrderAddrVo(orderAddressServer.getOrderAddr(orderId));
        orderDetailVo.setPhaseVos(orderPhaseServer.getOrderPhase(orderId));
        orderDetailVo.setOrderPayVo(orderPayServer.getOrderPay(orderId));
        List<DistVo> list = walletApi.getDistOrder(orderId).getResult();
        orderDetailVo.setDistVo(list);
        List<OrderAddrVo> orderAddrs = orderAddressServer.getOrderAddrs(orderId);
        orderDetailVo.setOrderAddrVos(orderAddrs);
        List<OrderSpuVo> orderSpu = orderSpuServer.getOrderSpu(orderId);
        for (OrderAddrVo orderAddrVo : orderAddrs) {
            for (OrderSpuVo orderSpuVo : orderSpu) {
                if (orderAddrVo.getSkuId().equals(orderSpuVo.getSkuId())) {
                    orderSpuVo.setAddrId(orderAddrVo.getId());
                }

            }
        }
        orderDetailVo.setSpuVos(orderSpu);
        //售后信息
        QueryAfterSaleOrderListBo bo = new QueryAfterSaleOrderListBo();
        bo.setOrderId(orderId);
        List<AfterSaleOrder> afterSaleOrders = afterSaleOrderDao.queryAfterSaleOrderList(bo);
        orderDetailVo.setAfterSaleOrderVos(BeanConverUtils.convertBeanList(afterSaleOrders, AfterSaleOrderVo.class));
        orderDetailVo.setShopVo(shopApi.getShopForApi(orderInfoVo.getShopId()).getResult());
        return orderDetailVo;
    }

    /**
     * 查询用户订单详细信息api
     *
     * @param bo
     * @return
     */
    public OrderDetailsVo getOrderApiDetail(OrderApiBo bo) {
        OrderDetailsVo orderDetailVo = new OrderDetailsVo();
        ParamException.isTrue(bo.getAppId() == null, "appID为空");
        ParamException.isTrue(bo.getTimestamp() == null, "请求时间为空");
        SupplierBo supplierBo = new SupplierBo();
        supplierBo.setAppId(bo.getAppId());
        RestVo<PageVo<SupplierVo>> pageVoRestVo = goodsApi.querySupplierCategory(supplierBo);
        List<SupplierVo> data = pageVoRestVo.getResult().getData();
        ParamException.isTrue(data == null || data.size() == 0, "appID不存在");
        List<String> supplierList = data.stream().map(supplierVo -> supplierVo.getId()).collect(Collectors.toList());
        ParamException.isTrue(bo.getOrderId() == null, "主订单id为空");
        OrderListApiBo orderListApiBo = new OrderListApiBo();
        orderListApiBo.setOrderId(bo.getOrderId());
        orderListApiBo.setSupplierList(supplierList);
        List<OrderInfo> orderInfos = orderInfoDao.queryOrderSpuApiList(orderListApiBo);
        if (orderInfos != null && orderInfos.size() != 0) {
            orderDetailVo.setOrderInfoApiVo(BeanConverUtils.convertBean(orderInfos.get(0), OrderInfoApiVo.class));
            orderDetailVo.setOrderAddrVos(orderAddressServer.getOrderAddrs(bo.getOrderId()));
            orderDetailVo.setSpuVos(orderSpuServer.getOrderApiSpu(bo.getOrderId()));
        }
        return orderDetailVo;
    }

    public OrderInfoVo getOrderInfoVo(String orderId) {
        return BeanConverUtils.convertBean(orderInfoDao.selectByPrimaryKey(orderId), OrderInfoVo.class);
    }

    /**
     * 用户取消订单
     *
     * @param orderId
     * @param userId
     * @return
     */

    public void cancel(String orderId, String userId) {
        OrderInfo orderInfo = orderInfoDao.selectByPrimaryKey(orderId);
        orderInfoDao.orderClosed(orderId, userId, "用户手动取消订单");
        orderAddrDao.orderClosed(orderId);
        changeOrderSkuInventory(orderInfo, BaseEnum.StatusEnum.DISABLE.getCode());
        ((OrderInfoServer) AopContext.currentProxy()).pushWechatMsg(orderInfo);
    }

    @Async
    public void pushWechatMsg(OrderInfo orderInfo) {
        if (null != orderInfo) {
            String openId = userApi.getWechatOpenId(orderInfo.getUserId()).getResult();
            if (StrUtil.isNotEmpty(openId)) {
                String timeStr = DateUtil.formatDateTime(orderInfo.getGmtCreated());
                WxTemplateMsgBo template = new WxTemplateMsgBo();
                template.setTouser(openId);
                template.setTemplate_id(WechatTemplateEnum.ORDER_CANCEL.getTemplateId());
                template.setTopcolor("#353535");
                WxTemplateMsgBo.TemplateData data = template.new TemplateData();
                data.setFirst(template.new Node("尊敬的" + orderInfo.getUserName() + "，您的五八马订单已取消  ：", "#54529E"));
                data.setKeyword1(template.new Node(orderInfo.getId(), "#54529E"));
                data.setKeyword2(template.new Node(orderInfo.getAmount() + "元", "#54529E"));
                data.setKeyword3(template.new Node(timeStr, "#54529E"));
                data.setKeyword4(template.new Node("已取消", "#54529E"));
                data.setRemark(template.new Node("您的订单已成功取消，如需继续购买请重新下单！", "#353535"));
                template.setData(data);
                gateApi.tempMessagePush(template);
            }
        }
    }

    /**
     * 用户更新订单备注
     *
     * @param bo
     * @return
     */
    public void updateRemark(OrderUpdateBo bo) {
        ParamException.isNull(bo.getOrderId(), "订单id不能为空");
        orderInfoDao.updateRemark(bo);
    }

    /**
     * 用户更新订单地址
     *
     * @param bo
     * @return
     */
    public void updateAddr(OrderUpdateBo bo) {
        ParamException.isNull(bo.getOrderId(), "订单id不能为空");
        OrderAddr orderAddr = new OrderAddr();
        orderAddr.setOrderId(bo.getOrderId());
        List<OrderAddr> select = orderAddrDao.select(orderAddr);
        ParamException.isTrue(select == null || select.size() == 0);
        select.forEach(addr -> {
            ParamException.isTrue((!OrderEnum.AddrOrderStatus.UN_SEND.getCode().equals(addr.getType()) || !OrderEnum.OrderStatus.UN_PAY.getCode().equals(addr.getStatus())), "未付款的订单才可以修改地址");
        });
        if (StringUtils.hasText(bo.getRegionId())) {
            RegionVo regionVo = gateApi.geoRegion(bo.getRegionId()).getResult();
            ParamException.isNull(regionVo, "区域不存在");
            bo.setProvinceName(regionVo.getProvinceName());
            bo.setCityName(regionVo.getCityName());
            bo.setDistrictName(regionVo.getDistrictName());
        }
        orderAddrDao.updateAddr(bo);
    }


    /**
     * 发货
     *
     * @param bo
     */
    @Transactional(rollbackFor = Exception.class)
    public void orderDelivery(OrderDeliveryBo bo) {
        OrderInfo orderInfo = orderInfoDao.selectByPrimaryKey(bo.getOrderId());
        ParamException.isNull(orderInfo);
        ParamException.isFalse(OrderEnum.OrderStatus.PAYED.getCode().equals(orderInfo.getStatus()), "当前单据有售后或者已发货,无法发货");
        //ParamException.isTrue(1==(orderInfo.getIsAfterSale()==null?0:orderInfo.getIsAfterSale()),"当前单据有售后或者已经进行了售后,无法发货");
        checkAfterSale(orderInfo.getId());
        OrderInfo update = new OrderInfo();
        update.setId(bo.getOrderId());
        update.setStatus(OrderEnum.OrderStatus.SEND.getCode());
        update.setDeliveryTime(Instant.now());
        update.setRepairTime(DateUtil.addDay(DateUtil.addDay(Instant.now(), autoReceiveDay), overRepairTime));
        orderInfoDao.updateByPrimaryKeySelective(update);
        orderAddrDao.orderDelivery(bo);
        //自提自动收货
        if (bo.getLogisticsName() != null && OrderEnum.AddrOrderStatus.isIncludeName(bo.getLogisticsName())
                && OrderEnum.AddrOrderStatus.SELF.getName().equals(bo.getLogisticsName())) {
            orderInfoServer.receive(bo.getOrderId(), orderInfo.getUserId());
        }
        //((OrderInfoServer)AopContext.currentProxy()).nofity(bo,orderInfo);
    }

    /**
     * 按商品订单发货
     *
     * @param bo
     */
    @Transactional(rollbackFor = Exception.class)
    public void orderDeliveryBySpu(OrderDeliveryBo bo) {
        ParamException.isBlank(bo.getId(), "子订单id为空");
        List<String> list1 = Arrays.asList(bo.getId().split(","));
        for (String id : list1) {
            ParamException.isTrue(id == null, "子订单id为空");
            //单独发货子订单
            OrderListApiBo orderListApiBo = new OrderListApiBo();
            orderListApiBo.setId(id);
            List<OrderAddr> orderAddr = orderAddrDao.queryOrderAddrs(orderListApiBo);
            ParamException.isTrue(orderAddr == null || orderAddr.size() == 0, "订单已发货或者未付款");
            ParamException.isFalse(OrderEnum.OrderStatus.PAYED.getCode().equals(orderAddr.get(0).getStatus()), "订单不是待发货状态");
            String orderId = orderAddr.get(0).getOrderId();
            //更新发货单发货状态
            OrderAddr update = new OrderAddr();
            update.setDeliveryTime(Instant.now());
            update.setLogisticsName(bo.getLogisticsName());
            update.setLogisticsNo(bo.getLogisticsNo());
            update.setId(id);
            update.setType(1);
            update.setStatus(OrderEnum.OrderStatus.SEND.getCode());

            OrderSpu spu = new OrderSpu();
            spu.setOrderId(orderId);
            //未售后单据
            List<OrderSpu> orderSpus = orderSpuDao.select(spu).stream().filter(o -> o.getIsAfterSale() == null || o.getIsAfterSale() == 0).collect(Collectors.toList());
            //已售后单据
            List<OrderSpu> orderSpus2 = orderSpuDao.select(spu).stream().filter(o -> o.getIsAfterSale() != null && o.getIsAfterSale() != 0).collect(Collectors.toList());
            //判断是否售后
            if (orderSpus2 != null && orderSpus2.size() != 0) {
                for (OrderSpu orderSpu : orderSpus2) {
                    ParamException.isTrue(orderSpu.getSkuId().equals(orderAddr.get(0).getSkuId()), "当前商品已售后,不能进行发货");
                }
            }
            //判断当前发货是否进行售后 只有id在未售后的 orderSpus 里面的才能发货
            if (orderSpus != null && orderSpus.size() != 0) {
                for (OrderSpu orderSpu : orderSpus) {
                    if (orderSpu.getSkuId().equals(orderAddr.get(0).getSkuId())) {
                        orderAddrDao.updateByPrimaryKeySelective(update);
                    }
                }
            }
            //更新原订单发货状态
            OrderListApiBo orderListApiBo1 = new OrderListApiBo();
            orderListApiBo1.setOrderId(orderAddr.get(0).getOrderId());
            List<OrderAddr> listAll = orderAddrDao.queryOrderAddrs(orderListApiBo1);
            //查询未发货订单 list
            List<OrderAddr> list = listAll.stream()
                    .filter(o -> OrderEnum.AddrOrderStatus.UN_SEND.getCode().equals(o.getType())).collect(Collectors.toList());

            OrderInfo orderInfo = new OrderInfo();
            orderInfo.setId(orderAddr.get(0).getOrderId());
            orderInfo.setStatus(OrderEnum.OrderStatus.SEND.getCode());
            orderInfo.setDeliveryTime(Instant.now());
            //更新最长保修时间为 自动收货时间+保修时间
            orderInfo.setRepairTime(DateUtil.addDay(DateUtil.addDay(Instant.now(), autoReceiveDay), overRepairTime));

            //未发货订单 list 与已售后 orderSpus2 进行比较,如果相等,说明未发货的订单都进行了售后,更新状态成已发货
            if (list != null && list.size() != 0) {
                Integer num = 0;
                for (OrderAddr addr : list) {
                    for (OrderSpu orderSpu : orderSpus2) {
                        if (orderSpu.getSkuId().equals(addr.getSkuId())) {
                            num = num + 1;
                        }
                    }
                }
                if (num == list.size()) {
                    orderInfoDao.updateByPrimaryKeySelective(orderInfo);
                    //查询已发货自提订单 selfList 如果所有订单全是自提,更新状态已收货
                    listAll.removeAll(list);
                    autoReceiveSelf(listAll, orderId);
                }
            } else {
                orderInfoDao.updateByPrimaryKeySelective(orderInfo);
                //如果所有订单全是自提,更新状态已收货
                autoReceiveSelf(listAll, orderId);
            }
        }
    }

    /**
     * 自提自动收货
     */
    public void autoReceiveSelf(List<OrderAddr> listAll, String orderId) {
        List<OrderAddr> selfList = listAll.stream()
                .filter(o -> o.getLogisticsName() != null && OrderEnum.AddrOrderStatus.isIncludeName(o.getLogisticsName())
                        && OrderEnum.AddrOrderStatus.SELF.getName().equals(o.getLogisticsName())).collect(Collectors.toList());
        if (selfList.size() == listAll.size()) {
            OrderInfo orderInfo1 = orderInfoDao.selectByPrimaryKey(orderId);
            receive(orderId, orderInfo1.getUserId());
        }
    }

    /**
     * 订单发货api
     *
     * @param bo
     */
    @Transactional(rollbackFor = Exception.class)
    public void orderApiDelivery(OrderDeliveryApiBo bo) {

        ParamException.isTrue(bo.getAppId() == null, "appID不能为空");
        ParamException.isTrue(bo.getTimestamp() == null, "请求时间为空");
        SupplierBo supplierBo = new SupplierBo();
        supplierBo.setAppId(bo.getAppId());
        RestVo<PageVo<SupplierVo>> pageVoRestVo = goodsApi.querySupplierCategory(supplierBo);
        List<SupplierVo> data = pageVoRestVo.getResult().getData();
        ParamException.isTrue(data == null || data.size() == 0, "appID不存在");
        List<String> supplierList = data.stream().map(supplierVo -> {
            return supplierVo.getId();
        }).collect(Collectors.toList());
        bo.setSupplierList(supplierList);
        //ParamException.isFalse(ThirdPartEnum.ThirdPartCode.isIncludeCode(bo.getAppId()),"appID不存在或者已过期");
        ParamException.isTrue(bo.getDeliveryTime() == null, "发货时间为空");
        ParamException.isTrue(bo.getLogisticsCode() == null, "物流编码为空");
        ParamException.isTrue(bo.getLogisticsName() == null, "物流公司为空");
        ParamException.isTrue(bo.getLogisticsNo() == null, "物流单号为空");
        if (bo.getOrderId() != null && bo.getOrderId() != "") {
            ParamException.isTrue(bo.getOrderId() == null, "主订单id为空");
            //整单发货
            OrderListApiBo orderListApiBo = BeanConverUtils.convertBean(bo, OrderListApiBo.class);
            List<OrderInfo> orderInfos = orderInfoDao.queryOrderSpuApiList(orderListApiBo);
            ParamException.isTrue(orderInfos == null || orderInfos.size() == 0, "订单不存在");
            ParamException.isFalse(OrderEnum.OrderStatus.PAYED.getCode().equals(orderInfos.get(0).getStatus()), "订单不是待发货状态");
            checkAfterSale(bo.getOrderId());
            OrderInfo update = new OrderInfo();
            update.setId(bo.getOrderId());
            update.setDeliveryTime(Instant.now());
            update.setStatus(OrderEnum.OrderStatus.SEND.getCode());
            update.setRepairTime(DateUtil.addDay(DateUtil.addDay(Instant.now(), autoReceiveDay), overRepairTime));
            orderInfoDao.updateByPrimaryKeySelective(update);
            orderAddrDao.orderApiDelivery(bo);
        } else {
            ParamException.isBlank(bo.getId(), "子订单id为空");
            List<String> list1 = Arrays.asList(bo.getId().split(","));
            for (String id : list1) {
                ParamException.isTrue(id == null, "子订单id为空");
                //单独发货子订单
                OrderListApiBo orderListApiBo = new OrderListApiBo();
                orderListApiBo.setId(id);
                List<OrderAddr> orderAddr = orderAddrDao.queryApiOrderAddr(orderListApiBo);
                ParamException.isTrue(orderAddr == null || orderAddr.size() == 0, "订单不存在或者未付款");
                ParamException.isFalse(OrderEnum.OrderStatus.PAYED.getCode().equals(orderAddr.get(0).getStatus()), "订单不是待发货状态");
                String orderId = orderAddr.get(0).getOrderId();
                OrderAddr update = new OrderAddr();
                update.setDeliveryTime(Instant.now());
                update.setLogisticsName(bo.getLogisticsName());
                update.setLogisticsNo(bo.getLogisticsNo());
                update.setId(id);
                update.setType(1);
                update.setStatus(OrderEnum.OrderStatus.SEND.getCode());
                OrderSpu spu = new OrderSpu();
                spu.setOrderId(orderId);
                //未售后单据
                List<OrderSpu> orderSpus = orderSpuDao.select(spu).stream().filter(o -> o.getIsAfterSale() == null || o.getIsAfterSale() == 0).collect(Collectors.toList());
                //已售后单据
                List<OrderSpu> orderSpus2 = orderSpuDao.select(spu).stream().filter(o -> o.getIsAfterSale() != null && o.getIsAfterSale() != 0).collect(Collectors.toList());
                //判断是否售后
                if (orderSpus2 != null && orderSpus2.size() != 0) {
                    for (OrderSpu orderSpu : orderSpus2) {
                        ParamException.isTrue(orderSpu.getSkuId().equals(orderAddr.get(0).getSkuId()), "当前商品已售后,不能进行发货");
                    }
                }
                //判断当前发货是否进行售后
                if (orderSpus != null && orderSpus.size() != 0) {
                    for (OrderSpu orderSpu : orderSpus) {
                        if (orderSpu.getSkuId().equals(orderAddr.get(0).getSkuId())) {
                            orderAddrDao.updateByPrimaryKeySelective(update);
                        }
                    }
                }
                //更新订单发货状态
                OrderListApiBo orderListApiBo1 = new OrderListApiBo();
                orderListApiBo1.setOrderId(orderAddr.get(0).getOrderId());
                List<OrderAddr> list = orderAddrDao.queryOrderAddrs(orderListApiBo1).stream()
                        .filter(o -> OrderEnum.AddrOrderStatus.UN_SEND.getCode().equals(o.getType())).collect(Collectors.toList());
                OrderInfo orderInfo = new OrderInfo();
                orderInfo.setId(orderAddr.get(0).getOrderId());
                orderInfo.setStatus(OrderEnum.OrderStatus.SEND.getCode());
                orderInfo.setDeliveryTime(Instant.now());
                orderInfo.setRepairTime(DateUtil.addDay(DateUtil.addDay(Instant.now(), autoReceiveDay), overRepairTime));
                if (list != null && list.size() != 0) {
                    Integer num = 0;
                    for (OrderAddr addr : list) {
                        for (OrderSpu orderSpu : orderSpus2) {
                            if (orderSpu.getSkuId().equals(addr.getSkuId())) {
                                num = num + 1;
                            }
                        }
                    }
                    if (num == list.size()) {
                        orderInfoDao.updateByPrimaryKeySelective(orderInfo);
                    }
                } else {
                    orderInfoDao.updateByPrimaryKeySelective(orderInfo);
                }
            }
        }
    }

    /**
     * 检测是否在进行售后
     */
    public void checkAfterSale(String orderId) {
        QueryAfterSaleOrderListBo bo1 = new QueryAfterSaleOrderListBo();
        List<Integer> afterSaleBatch = new ArrayList<>();
        afterSaleBatch.add(OrderEnum.AfterStatus.APPLY.getCode());
        afterSaleBatch.add(OrderEnum.AfterStatus.ACCEPT.getCode());
        afterSaleBatch.add(OrderEnum.AfterStatus.SEND.getCode());
        afterSaleBatch.add(OrderEnum.AfterStatus.RECEIVED.getCode());
        afterSaleBatch.add(OrderEnum.AfterStatus.REFUNDING.getCode());
        afterSaleBatch.add(OrderEnum.AfterStatus.REFUNDED.getCode());
        afterSaleBatch.add(OrderEnum.AfterStatus.EXCHANGED.getCode());
        bo1.setAfterSaleBatch(afterSaleBatch);
        bo1.setOrderId(orderId);
        List<AfterSaleOrder> afterSaleOrders = afterSaleOrderDao.queryAfterSaleOrderList(bo1);
        ParamException.isFalse(CollectionUtils.isEmpty(afterSaleOrders), "当前单据有售后或者已经进行了售后,无法发货");
    }


    /**
     * 获取用户订单
     *
     * @param orderId
     * @return
     */
    public OrderInfoVo getUserOrder(String orderId, String userId) {
        OrderInfo orderInfo = orderInfoDao.selectByPrimaryKey(orderId);
        ParamException.isNull(orderInfo);
        if (StringUtils.hasText(userId)) {
            IllegalException.isFalse(userId.equals(orderInfo.getUserId()));
        }
        return BeanUtil.copyProperties(orderInfo, OrderInfoVo.class);
    }

    /**
     * 店铺确认自提订单
     *
     * @param confirmOrderBo
     */
    public void shopConfirmOrder(ShopConfirmOrderBo confirmOrderBo) {
        OrderInfo orderInfo = orderInfoDao.selectByPrimaryKey(confirmOrderBo.getOrderId());
        ParamException.isNull(orderInfo, "订单不存在");
        IllegalException.isFalse(orderInfo.getShopId().equals(confirmOrderBo.getShopId()), "您无权访问该数据");
        ParamException.isFalse(OrderEnum.DeliveryType.ZT.getCode().equals(orderInfo.getDeliveryType()), "只有自提订单才能核销");
        ParamException.isFalse(OrderEnum.OrderStatus.PAYED.getCode().equals(orderInfo.getStatus()), "当前订单状态还不能核销");
        OrderAddrVo orderAddrVo = orderAddressServer.getOrderAddr(orderInfo.getId());
        ParamException.isFalse(confirmOrderBo.getDeliveryCode().equals(orderAddrVo.getDeliveryCode()), "取件码不正确");
        receive(orderInfo);
    }

    /**
     * 确认自提订单
     *
     * @param confirmOrderBo
     */
    public void confirmOrder(ShopConfirmOrderBo confirmOrderBo) {
        OrderInfo orderInfo = orderInfoDao.selectByPrimaryKey(confirmOrderBo.getOrderId());
        ParamException.isNull(orderInfo, "订单不存在");
        ParamException.isFalse(OrderEnum.DeliveryType.ZT.getCode().equals(orderInfo.getDeliveryType()), "只有自提订单才能核销");
        ParamException.isFalse(OrderEnum.OrderStatus.PAYED.getCode().equals(orderInfo.getStatus()), "当前订单状态还不能核销");
        OrderAddrVo orderAddrVo = orderAddressServer.getOrderAddr(orderInfo.getId());
        ParamException.isFalse(confirmOrderBo.getDeliveryCode().equals(orderAddrVo.getDeliveryCode()), "取件码不正确");
        receive(orderInfo);
    }


    /**
     * 商家发货
     *
     * @param deliveryBo
     */
    public void shopDelivery(ShopDeliveryBo deliveryBo) {
        OrderInfo orderInfo = orderInfoDao.selectByPrimaryKey(deliveryBo.getOrderId());
        ParamException.isNull(orderInfo, "订单不存在");
        IllegalException.isFalse(orderInfo.getShopId().equals(deliveryBo.getShopId()), "您无权访问该数据");
        ParamException.isFalse(OrderEnum.OrderStatus.PAYED.getCode().equals(orderInfo.getStatus()), "当前订单状态无法发货");
        //快递
        if (OrderEnum.DeliveryType.KD.getCode().equals(deliveryBo.getDeliveryType())) {
            ParamException.isTrue(StrUtil.isEmpty(deliveryBo.getLogisticsCode()), "物流公司编号不能为空");
            ParamException.isTrue(StrUtil.isEmpty(deliveryBo.getLogisticsNo()), "物流单号不能为空");
        }
        OrderInfo update = new OrderInfo();
        update.setId(deliveryBo.getOrderId());
        update.setStatus(OrderEnum.OrderStatus.SEND.getCode());
        update.setDeliveryTime(Instant.now());
        update.setRepairTime(DateUtil.addDay(DateUtil.addDay(Instant.now(), autoReceiveDay), overRepairTime));
        update.setDeliveryType(deliveryBo.getDeliveryType());
        orderInfoDao.updateByPrimaryKeySelective(update);
        orderAddressServer.orderDelivery(deliveryBo);
    }


    /**
     * 获取用户订单
     *
     * @param masterOrderId
     * @param userId
     * @return
     */
    public List<OrderInfo> getUserMasterOrder(String masterOrderId, String userId) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setMasterOrderId(masterOrderId);
        orderInfo.setUserId(userId);
        List<OrderInfo> orderInfoList = orderInfoDao.select(orderInfo);
        ParamException.isTrue(orderInfoList == null || orderInfoList.size() == 0);
        for (OrderInfo info : orderInfoList) {
            IllegalException.isFalse(OrderEnum.OrderStatus.UN_PAY.getCode().equals(info.getStatus()), "子订单不是待付款状态");
            IllegalException.isTrue(Instant.now().isAfter(info.getExpirationTime()), "订单已经超时请重新下单");
        }
        OrderInfoMaster orderInfoMaster = new OrderInfoMaster();
        orderInfoMaster.setUserId(userId);
        orderInfoMaster.setId(masterOrderId);
        OrderInfoMaster orderInfoMaster1 = orderInfoMasterDao.selectOne(orderInfoMaster);
        ParamException.isNull(orderInfoMaster1);
        return orderInfoList;
    }

    /**
     * 用户签收订单
     *
     * @param orderId
     * @param userId
     * @return
     */
    public void receive(String orderId, String userId) {
        OrderInfo orderInfo = orderInfoDao.selectByPrimaryKey(orderId);
        ParamException.isNull(orderInfo);
        if (StringUtils.hasText(userId)) {
            IllegalException.isFalse(userId.equals(orderInfo.getUserId()));
        }
        IllegalException.isFalse(OrderEnum.OrderStatus.SEND.getCode().equals(orderInfo.getStatus()));
        receive(orderInfo);
    }

    public void autoReceive() {
        List<OrderInfo> orderInfos = orderInfoDao.queryDeliveryOrder(DateUtil.addDay(Instant.now(), -autoReceiveDay));
        for (OrderInfo orderInfo : orderInfos) {
            if (orderInfo.getDeliveryType() != null && !OrderEnum.DeliveryType.ZT.getCode().equals(orderInfo.getDeliveryType())) {
                receive(orderInfo);
            }
        }
    }

    public void autoZtReceive() {
        List<OrderInfo> orderInfos = orderInfoDao.queryZtOrder(DateUtil.addDay(Instant.now(), -ztAutoReceiveDay));
        for (OrderInfo orderInfo : orderInfos) {
            receive(orderInfo);
        }
    }

    public void autoLocalReceive() {
        List<OrderInfo> orderInfos = orderInfoDao.queryLocalDeliveryReceive(DateUtil.addDay(Instant.now(), -local_AutoReceiveDay));
        for (OrderInfo orderInfo : orderInfos) {
            receive(orderInfo);
        }
    }

    /**
     * 订单收货
     *
     * @param orderInfo
     */
    private void receive(OrderInfo orderInfo) {
        OrderInfo orderInfo1 = new OrderInfo();
        orderInfo1.setId(orderInfo.getId());
        orderInfo1.setStatus(OrderEnum.OrderStatus.RECEIVED.getCode());
        orderInfo1.setFinishTime(Instant.now());
        orderInfo1.setConfirmTime(Instant.now());
        orderInfo1.setRepairTime(DateUtil.addDay(Instant.now(), overRepairTime));
        orderInfoDao.updateByPrimaryKeySelective(orderInfo1);
        orderAddrDao.receive(orderInfo1);
        //通知订单分消同步订单状态
        rabbitTemplate.convertAndSend(RabbitMqConstants.DIST_ORDER_CALCULATE_QUEUE, JSON.toJSONString(orderInfoDao.selectByPrimaryKey(orderInfo.getId())));
    }

    /**
     * 完成支付
     */
    public void completePayment(OrderPay orderPay) {
        OrderInfo orderInfo = orderInfoDao.selectByPrimaryKey(orderPay.getOrderId());
        ParamException.isNull(orderInfo);
        //   ParamException.isFalse(OrderEnum.OrderStatus.UN_PAY.getCode().equals(orderInfo.getStatus()));
        OrderInfo update = new OrderInfo();
        update.setId(orderPay.getOrderId());
        update.setPayTime(Instant.now());
        update.setPayAmount(orderInfo.getPayAmount().add(orderPay.getAmount()));
        update.setPaymentType(orderPay.getPayType());
        update.setThisPayAmount(BigDecimal.ZERO);
        update.setStatus(OrderEnum.OrderStatus.PAYED.getCode());
        update.setPaymentType(orderPay.getPayType());
        //如果是自提订单状态直接改成已发货
/*        if(OrderEnum.DeliveryType.ZT.getCode().equals(orderInfo.getDeliveryType())){
            update.setStatus(OrderEnum.OrderStatus.SEND.getCode());
        }*/
        if (OrderEnum.PayType.PHASE.getCode().equals(orderInfo.getPayType())) {
            OrderPhaseVo orderPhaseVo = orderPhaseServer.getNoPayPhase(orderInfo.getId());
            //如果订单还存在未支付阶段则不更新订单状态更新订单开始和结束时间
            if (orderPhaseVo != null) {
                update.setStatus(null);
                update.setStartPayTime(orderPhaseVo.getStartTime());
                update.setThisPayAmount(orderPhaseVo.getAmount());
                update.setExpirationTime(orderPhaseVo.getEndTime());
            }
        }
        orderInfoDao.updateByPrimaryKeySelective(update);
        redisService.getHashOps().increment(RedisKey.DATA_TODAY_CHART.getKey(), DataEnum.TodayData.PAYMENTS.name(), orderPay.getAmount().doubleValue());
        //核销优惠券
        if (StringUtils.hasText(orderInfo.getCouponId())) {
            checkCoupon(Arrays.asList(orderInfo.getCouponId().split(",")), Boolean.TRUE);

        }
        //如果订单结算完成通知发货
        if (!OrderEnum.OrderStatus.UN_PAY.getCode().equals(update.getStatus())) {
            OrderInfo info = orderInfoDao.selectByPrimaryKey(orderPay.getOrderId());
            //同步分销订单
            ParamException.isNull(info, "订单不存在 orderI:" + orderInfo.getId());
            //更新发货信息
            orderAddressServer.orderPayConfirm(info);
            String disOrder = JSON.toJSONString(info);
            //通知分消对订单分消信息进行结算
            rabbitTemplate.convertAndSend(RabbitMqConstants.DIST_ORDER_CALCULATE_QUEUE, disOrder);
            ((OrderInfoServer) AopContext.currentProxy()).pushMessage(orderInfo);
        }
    }

    @Async
    public void pushMessage(OrderInfo orderInfo) {
        if (StrUtil.isNotEmpty(orderInfo.getShopId()) && orderInfo.getPlatformTag() == 1) {
            WebSocketMessageBo wsMessageBo = new WebSocketMessageBo();
            wsMessageBo.setSessionId(orderInfo.getShopId());
            wsMessageBo.setPk(BaseEnum.ProductEnum.SHOP_CONSOLE.getName());
            wsMessageBo.setType(0);
            wsMessageBo.setBizId(orderInfo.getId());
            wsMessageBo.setMessage(WebSocketMessageEnum.PushSceneEnum.SHOP_ORDER.getMsg());
            wsMessageBo.setPushScene(WebSocketMessageEnum.PushSceneEnum.SHOP_ORDER.getCode());
            messageApi.pushToWeb(wsMessageBo);
        }
    }


    /**
     * 发送订单超时任务
     *
     * @param orderInfo
     */
    public void sentOrderTimeoutMsg(OrderInfo orderInfo) {
        log.info("开始发送延迟订单消息 orderInfo={},expirationTime={}", JSON.toJSONString(orderInfo), expirationTime);
        rabbitTemplate.convertAndSend(RabbitMqConstants.ORDER_TIMEOUT_DL_QUEUE, orderInfo.getId(), (Message message) -> {
            message.getMessageProperties().setExpiration(String.valueOf(expirationTime * 60 * 1000));
            return message;
        });
    }

    /**
     * 记录第三方调用信息
     *
     * @param thirdPartRecordBo
     */
    @Transactional(rollbackFor = Exception.class)
    public void thirdPartRecord(ThirdPartRecordBo thirdPartRecordBo) {
        ThirdPartRecord thirdPartRecord = BeanConverUtils.convertBean(thirdPartRecordBo, ThirdPartRecord.class);
        thirdPartRecordDao.insert(thirdPartRecord);
    }

    /**
     * 订单自动过期
     *
     * @param orderNo
     */
    @Transactional(rollbackFor = Exception.class)
    public void orderAutoClosed(String orderNo) {
        //主动查询当前订单是否有支付（防止三方回调出问题）
        // orderPayServer.queryWxPayStatus(orderNo);
        OrderInfo orderInfo = orderInfoDao.selectByPrimaryKey(orderNo);
        ParamException.isNull(orderInfo, "订单号不存在");
        //不是未支付状态的直接放弃
        if (!OrderEnum.OrderStatus.UN_PAY.getCode().equals(orderInfo.getStatus())) {
            log.warn("orderNo={},订单已不是取消状态放弃关闭", orderNo);
            return;
        }
        //过期时间没到的消息直接放弃 交给定时任务处理
        if (orderInfo.getExpirationTime().isAfter(Instant.now())) {
            log.warn("orderNo={},订单结束时间未到放弃关闭", orderNo);
            return;
        }
        orderInfoDao.orderClosed(orderNo, orderInfo.getUserId(), Constant.CLOSE_EXPIRATION_MSG);
        orderAddrDao.orderClosed(orderNo);
        changeOrderSkuInventory(orderInfo, BaseEnum.StatusEnum.DISABLE.getCode());
    }

    public void orderAutoClosed() {
        List<OrderInfo> orderInfos = orderInfoDao.selectExpirationOrder();
        orderInfos.forEach(orderInfo -> {
            //关闭订单
            orderInfoDao.orderClosed(orderInfo.getId(), orderInfo.getUserId(), Constant.CLOSE_EXPIRATION_MSG);
            orderAddrDao.orderClosed(orderInfo.getId());
            //还原库存
            changeOrderSkuInventory(orderInfo, BaseEnum.StatusEnum.DISABLE.getCode());
        });
    }


    @Async
    public void deleteShoppingCart(List<OrderSpu> orderSpus, String userId) {
        goodsApi.deleteShoppingCard(orderSpus.stream().map(OrderSpu::getSkuCode).collect(Collectors.toList()), userId);
    }

    /**
     * 1 创建订单减库存 0 取消订单加库存
     *
     * @param type
     */
    public void changeOrderSkuInventory(OrderInfo orderInfo, Integer type) {
        if (OrderEnum.PayType.PHASE.getCode().equals(orderInfo.getPayType())) {
            return;
        }
        //只有普通订单才进行库存操作活动订单走活动库存
        if (OrderEnum.OrderWay.NORMAL.getCode().equals(orderInfo.getOrderType())
                || OrderEnum.OrderWay.LIMIT_TIME.getCode().equals(orderInfo.getOrderType())
                || OrderEnum.OrderWay.DISCOUNT.getCode().equals(orderInfo.getOrderType())) {
            List<OrderSpuVo> orderSpuVos = orderSpuServer.getOrderSpu(orderInfo.getId());
            ChangeStockBo changeStockBo = new ChangeStockBo();
            Map<String, Integer> skus = orderSpuVos.stream().
                    collect(Collectors.toMap(OrderSpuVo::getSkuCode, skuList -> skuList.getSkuQty()));
            List<SkuSaleBo> skuSaleDtoList = orderSpuVos.stream().map(orderSpuVo -> {
                SkuSaleBo skuSaleDto = new SkuSaleBo();
                skuSaleDto.setItemId(orderSpuVo.getItemId());
                skuSaleDto.setBarcode(orderSpuVo.getSkuCode());
                skuSaleDto.setSkuQty(orderSpuVo.getSkuQty());
                skuSaleDto.setRealPrice(orderSpuVo.getRealPrice());
                return skuSaleDto;
            }).collect(Collectors.toList());
            changeStockBo.setSkus(skus);
            changeStockBo.setType(type);
            changeStockBo.setOrderType(orderInfo.getOrderType());
            changeStockBo.setSkuSaleList(skuSaleDtoList);
            goodsApi.changeStock(changeStockBo);
        }
        //只有是秒杀订单才去减活动库存
        if (OrderEnum.OrderWay.SEC_KILL.getCode().equals(orderInfo.getOrderType()) && BaseEnum.StatusEnum.DISABLE.getCode().equals(type)) {
            seckillService.secondKillOrderNotify(null, orderInfo.getMasterOrderId(), OrderEnum.PayStatus.FILL.getCode());
        }
    }


    public void exportOrderList(QueryOrderListBo bo, HttpServletResponse response) throws Exception {
        //文件名
        String fileName = "OrderInfo_" + (new Date()).toString();
        //sheet名
        String sheetName = "订单详情sheet";
        //表头集合，作为表头参数
        String title = "订单编号,商品名称,商品规格,商品编码,sku编码,购买数量,零售价,买家,下单日期,配送方式,收货人信息,商品总价,订单金额,实际支付,支付方式,订单类型,订单状态,支付状态,发货状态,买家留言,卖家备注,收货人所在省,收货人所在市,收货人所在县/区,售后状态,售后类型";
        String[] split = title.split(",");
        List<String> titleList = new ArrayList<>();
        Arrays.stream(split).forEach(o -> {
            titleList.add(o);
        });

        List<ExportOrderInfo> exportOrderInfoVos = orderInfoDao.queryExportOrderList(bo);
        List<ExportOrderInfo> excelJSONList = new ArrayList<>();
        excelJSONList.addAll(exportOrderInfoVos);

        String[] params = new String[]{"未发货", "已发货"};
        //从第一行开始，到最后一行结束，设置第4列为下拉选项
        OutExcelQuery outExcelQuery = new OutExcelQuery(1, -1, 18, 18, params);
        //调取封装的方法，传入相应的参数
        HSSFWorkbook workbook = ExcelUtil.createExcel(sheetName, titleList, excelJSONList, outExcelQuery);

        //输出Excel文件
        OutputStream output = response.getOutputStream();
        response.reset();
        //中文名称要进行编码处理
        response.setHeader("Content-disposition", "attachment; filename=" + new String(fileName.getBytes("GB2312"), "ISO8859-1") + ".xls");
        response.setContentType("application/x-xls");
        workbook.write(output);
        output.close();
    }

    public Integer getRepairTime() {
        return overRepairTime;
    }

    public StatisticsVo getStatistics() {

        //1，每日注册用户数（区分小程序和app）

        //2，每日短信发送条数

        //3，每日成交金额（区分支付宝，微信，区分小程序，app，区分商品，和话费充值）

        //4，每日成交订单数（区分商品订单，话费充值订单）
        //List<StatisticsOrderVo>
        //5,   每日活跃用户数（区分小程序和app，区分正常用户，访客，根据当日调用接口数据来统计）

        return null;
    }

    /**
     * 查询话费充值订单
     */
    public List<MobileRechargeRecordVo> queryStatisticsMobileOrder() {
        PageBo<MobileRechargeRecordPageBo> pageBo = new PageBo<>();
        MobileRechargeRecordPageBo bo = new MobileRechargeRecordPageBo();
        bo.setStatus(MobileConfigEnum.RechargeEnum.SUCCESS.getCode());
        bo.setStartTime(DateUtil.getTimesMorning(-1));
        bo.setEndTime(DateUtil.getTimesNight(-1));
        pageBo.setParam(bo);
        pageBo.setPageSize(500);
        List<MobileRechargeRecordVo> rechargeRecordVos = gateApi.page(pageBo).getResult().getData();
        return rechargeRecordVos;
    }

    /**
     * 查询商品订单
     */
    public List<OrderInfoVo> queryStatisticsOrder() {
        QueryOrderListBo bo = new QueryOrderListBo();
        bo.setStartPayTime(DateUtil.getTimesMorning(-1));
        bo.setEndPayTime(DateUtil.getTimesNight(-1));
        List<OrderInfoVo> orderInfoVos = BeanConverUtils.convertBeanList(orderInfoDao.queryOrderSpuList(bo), OrderInfoVo.class);
        return orderInfoVos;
    }

    /**
     * 查询短信信息
     */
    public List<LoanSentSmsFlowBo> queryStatisticsSms() {
        PageBo<SentSmsFlowDto> pageBo = new PageBo<>();
        SentSmsFlowDto bo = new SentSmsFlowDto();
        bo.setStartTime(DateUtil.getTimesMorning(-1));
        bo.setEndTime(DateUtil.getTimesNight(-1));
        pageBo.setParam(bo);
        pageBo.setPageSize(500);
        List<LoanSentSmsFlowBo> sentSmsFlowBos = messageApi.getSmsPage(pageBo).getResult().getData();
        return sentSmsFlowBos;
    }

    public void updateRealStock(PageBo<ItemListApiBo> boPageBo) {
        ItemListApiBo bo = boPageBo.getParam();
        ParamException.isBlank(bo.getBarcode(), "barcode为空");
        checkAppIdValue(bo);
        goodsApi.updateRealStock(boPageBo);
    }

    public RestVo<PageVo<SkuVo>> index(PageBo<ItemListApiBo> boPageBo) {
        ItemListApiBo bo = boPageBo.getParam();
        checkAppIdValue(bo);
        return goodsApi.index(boPageBo);
    }

    public RestVo<PageVo<ItemApiVo>> mainiItemlist(PageBo<ItemListApiBo> boPageBo) {
        ItemListApiBo bo = boPageBo.getParam();
        checkAppIdValue(bo);
        return goodsApi.mainiItemlist(boPageBo);
    }

    private void checkAppIdValue(ItemListApiBo bo) {
        ParamException.isTrue(bo.getAppId() == null, "appID为空");
        ParamException.isTrue(bo.getTimestamp() == null, "请求时间为空");
        SupplierBo supplierBo = new SupplierBo();
        supplierBo.setAppId(bo.getAppId());
        RestVo<PageVo<SupplierVo>> pageVoRestVo = goodsApi.querySupplierCategory(supplierBo);
        List<SupplierVo> data = pageVoRestVo.getResult().getData();
        ParamException.isTrue(data == null || data.size() == 0, "appID不存在");
    }

    public ShopOrderDataVo getShopData(String shopId) {
        ParamException.isBlank(shopId, "门店id为空");
        ShopOrderDataVo vo = new ShopOrderDataVo();
        //今日数据统计
        ShopOrderCountVo todayDate = getTodayData(shopId);
        if (todayDate == null) {
            vo.setTodayAmount(BigDecimal.ZERO);
            vo.setTodayOrderCount(0);
        } else {
            vo.setTodayAmount(todayDate.getAmount());
            vo.setTodayOrderCount(todayDate.getOrderCount());
        }
        //本月数据统计
        ShopOrderCountVo monthData = getMonthData(shopId);
        if (monthData == null) {
            vo.setMonthAmount(BigDecimal.ZERO);
            vo.setMonthOrderCount(0);
        } else {
            vo.setMonthAmount(monthData.getAmount());
            vo.setMonthOrderCount(monthData.getOrderCount());
        }
        //待发货数据统计
        ShopOrderCountVo unsendData = getUnsendData(shopId);
        if (unsendData == null) {
            vo.setUnsendOrderCount(0);
        } else {
            vo.setUnsendOrderCount(unsendData.getOrderCount());
        }
        //成交数据统计
        ShopOrderCountVo receivedData = getReceivedData(shopId);
        if (receivedData == null) {
            vo.setReceivedCount(0);
        } else {
            vo.setReceivedCount(receivedData.getOrderCount());
        }
        //售后待处理数量统计
        QueryAfterSaleOrderListBo bo = new QueryAfterSaleOrderListBo();
        bo.setShopId(shopId);
        List<Integer> afterSaleBatch = Arrays.asList(new Integer[]{1, 2, 3, 4, 5});
        bo.setAfterSaleBatch(afterSaleBatch);
        Integer afterSaleCount = shopAfterSaleOrderDao.queryAfterSaleOrderCount(bo);
        if (afterSaleCount == null) {
            vo.setUnAfterSaleCount(0);
        } else {
            vo.setUnAfterSaleCount(afterSaleCount);
        }
        return vo;
    }

    /**
     * 今日数据统计
     */
    private ShopOrderCountVo getTodayData(String shopId) {
        QueryOrderListBo bo = new QueryOrderListBo();
        bo.setShopId(shopId);
        List<String> status = Arrays.asList(new String[]{"1", "2", "3", "5", "6"});
        bo.setStatuss(status);
        bo.setStartTime(DateUtil.getTimesMorning());
        bo.setEndTime(DateUtil.getTimesNight());
        //今日数据统计
        return orderInfoDao.queryShopOrderList(bo);
    }

    /**
     * 本月数据统计
     */
    private ShopOrderCountVo getMonthData(String shopId) {
        QueryOrderListBo bo = new QueryOrderListBo();
        bo.setShopId(shopId);
        List<String> status = Arrays.asList(new String[]{"1", "2", "3", "5", "6"});
        bo.setStatuss(status);
        bo.setStartTime(DateUtil.getFirstDayMonth(Instant.now()));
        //本月数据统计
        return orderInfoDao.queryShopOrderList(bo);
    }

    /**
     * 待发货数据统计
     */
    private ShopOrderCountVo getUnsendData(String shopId) {
        QueryOrderListBo bo = new QueryOrderListBo();
        bo.setShopId(shopId);
        bo.setStatus("1");
        return orderInfoDao.queryUnsendOrder(bo);
    }

    /**
     * 成交数据统计
     */
    private ShopOrderCountVo getReceivedData(String shopId) {
        QueryOrderListBo bo = new QueryOrderListBo();
        bo.setShopId(shopId);
        bo.setStatus("3");
        return orderInfoDao.queryUnsendOrder(bo);
    }

    public UserOrderCountVo getUserOrderCount(String userId) {
        UserOrderCountVo userOrderCountVo = new UserOrderCountVo();
        UserOrderCountVo vo = orderInfoDao.queryUserOrderCount(userId);
        if (vo != null) {
            userOrderCountVo.setUnPayCount(vo.getUnPayCount());
            userOrderCountVo.setUnReceiveCount(vo.getUnReceiveCount());
            userOrderCountVo.setUnSendCount(vo.getUnSendCount());
        }
        //查询售后单
        QueryAfterSaleOrderListBo bo = new QueryAfterSaleOrderListBo();
        bo.setUserId(userId);
        List<Integer> afterSaleBatch = new ArrayList<>();
        afterSaleBatch.add(1);
        afterSaleBatch.add(2);
        afterSaleBatch.add(3);
        afterSaleBatch.add(4);
        afterSaleBatch.add(5);
        bo.setAfterSaleBatch(afterSaleBatch);
        Integer afterSaleOrderCount = afterSaleOrderDao.queryAfterSaleOrderCount(bo);
        if (afterSaleOrderCount != null) {
            userOrderCountVo.setAfterSaleCount(afterSaleOrderCount);
        } else {
            userOrderCountVo.setAfterSaleCount(0);
        }
        return userOrderCountVo;
    }

    public UserOrderCountVo getWbmUserOrderCount(String userId) {
        UserOrderCountVo userOrderCountVo = new UserOrderCountVo();
        ShopVo shopVo = shopApi.getShopByUserId(userId).getResult();
        ParamException.isNull(shopVo, "当前用户门店不存在");
        UserOrderCountVo vo = orderInfoDao.queryWbmUserOrderCount(shopVo.getId());
        if (vo != null) {
            userOrderCountVo.setUnPayCount(vo.getUnPayCount());
            userOrderCountVo.setUnReceiveCount(vo.getUnReceiveCount());
            userOrderCountVo.setUnSendCount(vo.getUnSendCount());
            userOrderCountVo.setReceiveCount(vo.getReceiveCount());
        }
        return userOrderCountVo;
    }

    public UserOrderCountVo getWbmUserOrderCount(String shopId, String openId) {
        UserOrderCountVo userOrderCountVo = new UserOrderCountVo();
        ShopVo shopVo = shopApi.queryShopByOpenIdApi(openId, shopId).getResult();
        ParamException.isNull(shopVo, "当前用户门店不存在");
        UserOrderCountVo vo = orderInfoDao.queryWbmUserOrderCount(shopVo.getId());
        if (vo != null) {
            userOrderCountVo.setUnPayCount(vo.getUnPayCount());
            userOrderCountVo.setUnReceiveCount(vo.getUnReceiveCount());
            userOrderCountVo.setUnSendCount(vo.getUnSendCount());
            userOrderCountVo.setReceiveCount(vo.getReceiveCount());
        }
        return userOrderCountVo;
    }


    /**
     * 获取物流
     *
     * @return
     */
    public List<LogisticsVo> getLogisticsList() {
        List<LogisticsVo> list = new ArrayList<>();
        for (LogisticsEnum.LogisticsList t : LogisticsEnum.LogisticsList.values()) {
            LogisticsVo vo = new LogisticsVo();
            vo.setCode(t.getCode());
            vo.setName(t.getName());
            list.add(vo);
        }
        return list;
    }

    public List<OrderInfoVo> getOrderByPhone(QueryOrderListBo bo) {
        List<OrderInfoVo> orderInfoVos = BeanConverUtils.convertBeanList(orderInfoDao.queryOrderByPhone(bo), OrderInfoVo.class);
        return orderInfoVos;
    }

    public void sendUnsendMsg() {
        log.info("========> sendUnsendMsg start!");
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setStatus(OrderEnum.OrderStatus.PAYED.getCode());
        List<OrderInfo> orderInfos = orderInfoDao.select(orderInfo);
        if (CollectionUtils.isEmpty(orderInfos)) {
            log.info("========> sendUnsendMsg return!");
            return;
        }
        List<String> shopIds = orderInfos.stream().filter(o -> o.getDeliveryType().equals(0) || o.getDeliveryType().equals(1))
                .map(OrderInfo::getShopId).distinct().collect(Collectors.toList());
        List<ShopVo> shopVos = shopApi.getShopListByIds(shopIds).getResult();
        for (ShopVo shopVo : shopVos) {
            //发送短信
            if (shopVo.getDefaultTag() == 1) {
                //发送钉钉消息
                DingTalkBo bo1 = new DingTalkBo();
                bo1.setMessage("");
                bo1.setChannel(StatisticsEnum.channel.UN_SEND_COUNT.getId());
                rabbitTemplate.convertAndSend(RabbitMqConstants.DINGDING_TALK_MESSAGE, JSON.toJSONString(bo1));
            } else {
                ((OrderInfoServer) AopContext.currentProxy()).sentSms(shopVo.getUserTel(), SmsTempCodeEnum.UN_SEND_ORDER.getCode(), null);
            }
        }
        log.info("========> sendUnsendMsg end!");
    }

    public void ztReceiveMsg(String orderId) {
        List<OrderAddr> orderAddrs = orderAddrDao.queryOrderAddrs(orderId);
        ParamException.isTrue(CollectionUtils.isEmpty(orderAddrs), "订单不存在");
        OrderAddr orderAddr = orderAddrs.get(0);
        ParamException.isTrue(!orderAddr.getStatus().equals(1) || !orderAddr.getDeliveryType().equals(2), "只有未收货自提订单可以提醒");
        ParamException.isTrue(ChronoUnit.HOURS.between(orderAddr.getLastSendSmsTime(), Instant.now()) < 6L, "每6小时只能发送一次提醒");
        OrderAddr addr = new OrderAddr();
        addr.setLastSendSmsTime(Instant.now());
        orderAddrDao.upateAdderByOrderId(addr, orderId);
        //发送短信
        OrderInfo orderInfo = orderInfoDao.selectByPrimaryKey(orderId);
        List<String> list = new ArrayList<>();
        list.add(orderInfo.getShopName());
        list.add(orderAddr.getDeliveryCode());
        ((OrderInfoServer) AopContext.currentProxy()).sentSms(orderAddr.getMobile(), SmsTempCodeEnum.UN_ZT_ORDER.getCode(), list);
    }


    @Async
    public void sentSms(String telPhone, String code, List<String> list) {
        TempSentSmsBo tempSentSmsBo = new TempSentSmsBo();
        tempSentSmsBo.setToPhone(telPhone);
        tempSentSmsBo.setTemplateCode(code);
        if (!CollectionUtils.isEmpty(list)) {
            tempSentSmsBo.setTemplateParam(list);
        }
        messageApi.sentSms(tempSentSmsBo);
    }

    public UserOrderDataVo queryUnDealOrder(String userId) {
        ParamException.isBlank(userId, "用户id为空");
        UserOrderDataVo vo = new UserOrderDataVo();
        //查询未处理售后订单
        QueryAfterSaleOrderListBo bo = new QueryAfterSaleOrderListBo();
        bo.setUserId(userId);
        bo.setAfterSaleBatch(Arrays.asList(new Integer[]{1, 2, 3, 4, 5}));
        Integer afterSaleOrderCount = shopAfterSaleOrderDao.queryAfterSaleOrderCount(bo);
        if (afterSaleOrderCount != null) {
            vo.setAfterSaleOrderCount(afterSaleOrderCount);
        } else {
            vo.setAfterSaleOrderCount(0);
        }
        return vo;
    }

    public QueryTrackVo queryLogistics(String id) {
        OrderAddr orderAddr = orderAddrDao.selectByPrimaryKey(id);
        ParamException.isNull(orderAddr, "物流信息不存在");
        if (!StringUtils.hasText(orderAddr.getLogisticsNo()) || (!StringUtils.hasText(orderAddr.getLogisticsCode()) && !StringUtils.hasText(orderAddr.getLogisticsName()))) {
            return null;
        }
        if (orderAddr.getDeliveryTime() != null && DateUtil.diffDays(Instant.now(), orderAddr.getDeliveryTime()) > 90) {
            throw new CommonException("物流订单已超出最大查询期限");
        }
        QueryBo bo = new QueryBo();
        bo.setCom(Optional.ofNullable(orderAddr.getLogisticsCode()).orElse(orderAddr.getLogisticsName()));
        bo.setNum(orderAddr.getLogisticsNo());
        bo.setPhone(orderAddr.getMobile());
        QueryTrackVo result = gateApi.queryLogistics(bo).getResult();
        StringJoiner sj = new StringJoiner("");
        if (StringUtils.hasText(orderAddr.getProvinceName())) {
            sj.add(orderAddr.getProvinceName());
        }
        if (StringUtils.hasText(orderAddr.getCityName())) {
            sj.add(orderAddr.getCityName());
        }
        if (StringUtils.hasText(orderAddr.getDistrictName())) {
            sj.add(orderAddr.getDistrictName());
        }
        if (StringUtils.hasText(orderAddr.getAddress())) {
            sj.add(orderAddr.getAddress());
        }
        result.setAddr(sj.toString());
        return result;
    }
}
